package org.az.netty_study.p04_netty初体验;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;

/**
 * 演示netty创建服务器
 */
public class HelloServer {
    public static void main(String[] args) {
        /**
         * 1.创建启动器ServerBootstrap
         *   ServerBootstrap负责组装netty的各个组件
         */
        ServerBootstrap server = new ServerBootstrap();
        /**
         * 2.添加boss和worker的EventLoopGroup(底层是线程池)
         *   EventLoop表示一对selector和thread，Group一组EventLoop,这组EventLoop包含boss和worker，也可以单独设置boss和worker的EventLoop
         *   boss:负责处理连接(accept)
         *   worker:负责处理连接通道上发生的读写事件(read,write)
         */
        server.group(new NioEventLoopGroup());
        /**
         * 3.设置服务器ServerSocketChannel的实现类
         */
        server.channel(NioServerSocketChannel.class);
        /**
         * 4.添加一些ChannelHandler
         *   连接建立后，就回调这些ChannelHandler
         */
        server.childHandler(
                //ChannelInitializer：表示初始化channel，这个handler的作用是添加别的handler
                new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        /**
                         * 6.添加具体的handler
                         *   这里的handler就是将来已经建立的channel上发生读写事件时，就会依次回调下面添加的handler
                         *   NioSocketChannel(SocketChannel的实现类)表示将来服务器与客户端连接建立后，就使用NioSocketChannel作为双方交流的通道
                         *   可以给NioSocketChannel添加多个handler，将来连接建立后，就依次回调这里定义的handler
                         *   channel里面的数据照样读到buffer里，只不过netty里的buffer是ByteBuf，ByteBuf可以理解为netty对ByteBuffer进行的封装
                         */
                        //1.StringDecoder是netty提供handler，能将ByteBuf(从channel里读到的)里的字节数据转为字符串，并把字符串流转给下一个handler
                        ch.pipeline().addLast(new StringDecoder());
                        //2.自定义handler，打印上一步转化的字符串
                        ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                            //表示读事件
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println(msg);
                            }
                        });
                    }
                }
        );
        /**
         * 7.绑定端口，启动
         */
        server.bind(9001);

    }
}
